home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.7 / tcpdump- / tcpdump-richard-1.7 / libpcap-0.0 / pcap-snit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-12  |  7.0 KB  |  294 lines

  1. /*
  2.  * Copyright (c) 1990, 1991, 1992, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef lint
  22. static  char rcsid[] =
  23.     "@(#)$Header: pcap-snit.c,v 1.33 94/06/23 13:51:17 leres Exp $ (LBL)";
  24. #endif
  25.  
  26. /*
  27.  * Modifications made to accomodate the new SunOS4.0 NIT facility by
  28.  * Micky Liu, micky@cunixc.cc.columbia.edu, Columbia University in May, 1989.
  29.  * This module now handles the STREAMS based NIT.
  30.  */
  31.  
  32. #include <sys/types.h>
  33. #include <sys/time.h>
  34. #include <sys/timeb.h>
  35. #include <sys/dir.h>
  36. #include <sys/fcntlcom.h>
  37. #include <sys/file.h>
  38. #include <sys/ioctl.h>
  39. #include <sys/socket.h>
  40. #include <sys/stropts.h>
  41.  
  42. #include <net/bpf.h>
  43. #include <net/if.h>
  44. #include <net/nit.h>
  45. #include <net/nit_if.h>
  46. #include <net/nit_pf.h>
  47. #include <net/nit_buf.h>
  48.  
  49. #include <netinet/in.h>
  50. #include <netinet/in_systm.h>
  51. #include <netinet/ip.h>
  52. #include <netinet/if_ether.h>
  53. #include <netinet/ip_var.h>
  54. #include <netinet/udp.h>
  55. #include <netinet/udp_var.h>
  56. #include <netinet/tcp.h>
  57. #include <netinet/tcpip.h>
  58.  
  59. #include <ctype.h>
  60. #include <errno.h>
  61. #include <stdio.h>
  62. #include <string.h>
  63.  
  64. #include "pcap-int.h"
  65.  
  66. /*
  67.  * The chunk size for NIT.  This is the amount of buffering
  68.  * done for read calls.
  69.  */
  70. #define CHUNKSIZE (2*1024)
  71.  
  72. /*
  73.  * The total buffer space used by NIT.
  74.  */
  75. #define BUFSPACE (4*CHUNKSIZE)
  76.  
  77. /* Forwards */
  78. static int nit_setflags(int, int, int, char *);
  79.  
  80. int
  81. pcap_stats_live(pcap_t *p, struct pcap_stat *ps)
  82. {
  83.     *ps = p->md.stat;
  84.     return (0);
  85. }
  86.  
  87. int
  88. pcap_read_live(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
  89. {
  90.     register int cc, n;
  91.     register struct bpf_insn *fcode = p->fcode.bf_insns;
  92.     register u_char *bp, *cp, *ep;
  93.     register struct nit_bufhdr *hdrp;
  94.     register struct nit_iftime *ntp;
  95.     register struct nit_iflen *nlp;
  96.     register struct nit_ifdrops *ndp;
  97.     register int caplen;
  98.  
  99.     cc = p->cc;
  100.     if (cc == 0) {
  101.         cc = read(p->fd, (char *)p->buffer, p->bufsize);
  102.         if (cc < 0) {
  103.             if (errno == EWOULDBLOCK)
  104.                 return (0);
  105.             sprintf(p->errbuf, "pcap_read: %s",
  106.                 pcap_strerror(errno));
  107.             return (-1);
  108.         }
  109.         bp = p->buffer;
  110.     } else
  111.         bp = p->bp;
  112.  
  113.     /*
  114.      * loop through each snapshot in the chunk
  115.      */
  116.     n = 0;
  117.     ep = bp + cc;
  118.     while (bp < ep) {
  119.         cp = bp;
  120.  
  121.         /* get past NIT buffer  */
  122.         hdrp = (struct nit_bufhdr *)cp;
  123.         cp += sizeof(*hdrp);
  124.  
  125.         /* get past NIT timer   */
  126.         ntp = (struct nit_iftime *)cp;
  127.         cp += sizeof(*ntp);
  128.  
  129.         ndp = (struct nit_ifdrops *)cp;
  130.         p->md.stat.ps_drop = ndp->nh_drops;
  131.         cp += sizeof *ndp;
  132.  
  133.         /* get past packet len  */
  134.         nlp = (struct nit_iflen *)cp;
  135.         cp += sizeof(*nlp);
  136.  
  137.         /* next snapshot        */
  138.         bp += hdrp->nhb_totlen;
  139.  
  140.         caplen = nlp->nh_pktlen;
  141.         if (caplen > p->snapshot)
  142.             caplen = p->snapshot;
  143.  
  144.         ++p->md.stat.ps_recv;
  145.  
  146.         if (fcode == NULL || bpf_filter(fcode, cp, nlp->nh_pktlen, caplen)) {
  147.             struct pcap_hdr h;
  148.             h.ts = ntp->nh_timestamp;
  149.             h.len = nlp->nh_pktlen;
  150.             h.caplen = caplen;
  151.             h.drops = ndp->nh_drops;
  152.             (*callback)(user, &h, cp);
  153.             if (++n >= cnt && cnt >= 0) {
  154.                 p->cc = ep - bp;
  155.                 p->bp = bp;
  156.                 return (n);
  157.             }
  158.         }
  159.     }
  160.     p->cc = 0;
  161.     return (n);
  162. }
  163.  
  164. static int
  165. nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
  166. {
  167.     u_long flags;
  168.     struct strioctl si;
  169.     struct timeval timeout;
  170.  
  171.     si.ic_timout = INFTIM;
  172.     if (to_ms != 0) {
  173.         timeout.tv_sec = to_ms / 1000;
  174.         timeout.tv_usec = (to_ms * 1000) % 1000000;
  175.         si.ic_cmd = NIOCSTIME;
  176.         si.ic_len = sizeof(timeout);
  177.         si.ic_dp = (char *)&timeout;
  178.         if (ioctl(fd, I_STR, (char *)&si) < 0) {
  179.             sprintf(ebuf, "NIOCSTIME: %s", pcap_strerror(errno));
  180.             return (-1);
  181.         }
  182.     }
  183.     flags = NI_TIMESTAMP | NI_LEN | NI_DROPS;
  184.     if (promisc)
  185.         flags |= NI_PROMISC;
  186.     si.ic_cmd = NIOCSFLAGS;
  187.     si.ic_len = sizeof(flags);
  188.     si.ic_dp = (char *)&flags;
  189.     if (ioctl(fd, I_STR, (char *)&si) < 0) {
  190.         sprintf(ebuf, "NIOCSFLAGS: %s", pcap_strerror(errno));
  191.         return (-1);
  192.     }
  193.     return (0);
  194. }
  195.  
  196. pcap_t *
  197. pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  198. {
  199.     struct strioctl si;        /* struct for ioctl() */
  200.     struct ifreq ifr;        /* interface request struct */
  201.     int chunksize = CHUNKSIZE;
  202.     int fd;
  203.     static char dev[] = "/dev/nit";
  204.     register pcap_t *p;
  205.  
  206.     p = (pcap_t *)malloc(sizeof(*p));
  207.     if (p == NULL) {
  208.         strcpy(ebuf, pcap_strerror(errno));
  209.         return (NULL);
  210.     }
  211.  
  212.     if (snaplen < 96)
  213.         /*
  214.          * NIT requires a snapshot length of at least 96.
  215.          */
  216.         snaplen = 96;
  217.  
  218.     bzero(p, sizeof(*p));
  219.     p->fd = fd = open(dev, O_RDONLY);
  220.     if (fd < 0) {
  221.         sprintf(ebuf, "%s: %s", dev, pcap_strerror(errno));
  222.         goto bad;
  223.     }
  224.  
  225.     /* arrange to get discrete messages from the STREAM and use NIT_BUF */
  226.     if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) {
  227.         sprintf(ebuf, "I_SRDOPT: %s", pcap_strerror(errno));
  228.         goto bad;
  229.     }
  230.     if (ioctl(fd, I_PUSH, "nbuf") < 0) {
  231.         sprintf(ebuf, "push nbuf: %s", pcap_strerror(errno));
  232.         goto bad;
  233.     }
  234.     /* set the chunksize */
  235.     si.ic_cmd = NIOCSCHUNK;
  236.     si.ic_timout = INFTIM;
  237.     si.ic_len = sizeof(chunksize);
  238.     si.ic_dp = (char *)&chunksize;
  239.     if (ioctl(fd, I_STR, (char *)&si) < 0) {
  240.         sprintf(ebuf, "NIOCSCHUNK: %s", pcap_strerror(errno));
  241.         goto bad;
  242.     }
  243.  
  244.     /* request the interface */
  245.     strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  246.     ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
  247.     si.ic_cmd = NIOCBIND;
  248.     si.ic_len = sizeof(ifr);
  249.     si.ic_dp = (char *)𝔦
  250.     if (ioctl(fd, I_STR, (char *)&si) < 0) {
  251.         sprintf(ebuf, "NIOCBIND: %s: %s",
  252.             ifr.ifr_name, pcap_strerror(errno));
  253.         goto bad;
  254.     }
  255.  
  256.     /* set the snapshot length */
  257.     si.ic_cmd = NIOCSSNAP;
  258.     si.ic_len = sizeof(snaplen);
  259.     si.ic_dp = (char *)&snaplen;
  260.     if (ioctl(fd, I_STR, (char *)&si) < 0) {
  261.         sprintf(ebuf, "NIOCSSNAP: %s", pcap_strerror(errno));
  262.         goto bad;
  263.     }
  264.     p->snapshot = snaplen;
  265.     if (nit_setflags(p->fd, promisc, to_ms, ebuf) < 0)
  266.         goto bad;
  267.  
  268.     (void)ioctl(fd, I_FLUSH, (char *)FLUSHR);
  269.     /*
  270.      * NIT supports only ethernets.
  271.      */
  272.     p->linktype = DLT_EN10MB;
  273.  
  274.     p->bufsize = BUFSPACE;
  275.     p->buffer = (u_char *)malloc(p->bufsize);
  276.     if (p->buffer == NULL) {
  277.         strcpy(ebuf, pcap_strerror(errno));
  278.         goto bad;
  279.     }
  280.     return (p);
  281.  bad:
  282.     if (fd >= 0)
  283.         close(fd);
  284.     free(p);
  285.     return (NULL);
  286. }
  287.  
  288. int
  289. pcap_setfilter_live(pcap_t *p, struct bpf_program *fp)
  290. {
  291.     p->fcode = *fp;
  292.     return (0);
  293. }
  294.